//
//  02_BasicOperators.swift
//  cnswift-demo
//
//  Created by wyang on 2022/7/21.
//  Copyright © 2022 YangWei. All rights reserved.
//

import Foundation

/// 基本运算符
class BasicOperators: SWDBaseObject {
    
    class func run() {
        
        let basicOperators = BasicOperators()
        
        // 2
        basicOperators.assignmentOperator()
        
        // 3.0
        basicOperators.arithmeticOperators()
        
        // 3.1
        basicOperators.remainderOperator()
        
        // 3.2
        basicOperators.unaryMinusOperator()
        
        // 3.3
        basicOperators.unaryPlusOperator()
        
        // 4.0
        basicOperators.compoundAssignmentOperators()
        
        // 5.0
        basicOperators.comparisonOperators()
        
        // 6.0
        basicOperators.ternaryConditionalOperator()
        
        // 7.0
        basicOperators.nilCoalescingOperator()
        
        // 8.1
        basicOperators.closedRangeOperator()
        
        // 8.2
        basicOperators.halfOpenRangeOperator()
        
        // 8.3
        basicOperators.oneSidedRanges()
        
        // 9.1
        basicOperators.logicalNOTOperator()
        
        // 9.2
        basicOperators.logicalANDOperator()
        
        // 9.3
        basicOperators.logicalOROperator()
        
        // 9.4
        basicOperators.combiningLogicalOperators()
        
        // 9.5
        basicOperators.explicitParentheses()
    }
    
    /// 2 赋值运算符
    func assignmentOperator() {
        
        let title = "2 赋值运算符";
        printStartLine(title)
        
        let b = 10
        var a = 5
        a = b
        print("a 现在是 \(a)")
        
        /*
         对元组赋值，元素会一次性地拆分成常量或变量：
         */
        let (x, y) = (1, 2)
        // x 等于 1, 同时 y 等于 2
        print("元组 (x, y) = \((x, y))")
        
        /*
         Swift 的赋值符号自身不会返回值，与 Objective-C 和 C 不同
         */
        /*
        var x1 = 1
        let y1 = 2
        if x1 = y1 { // 编译报错❌
            // x1 = y1 并不会返回任何值。
        }
         */
        
        printEndLine(title)
    }
    
    /// 3.0 算数运算符
    func arithmeticOperators() {
        
        let title = "3.0 算数运算符";
        printStartLine(title)
        
        print("1 + 2 = \(1 + 2)") // 3
        print("5 - 3  = \(5 - 3)") // 2
        print("2 * 3  = \(2 * 3)") // 6
        print("10.0 / 2.5  = \(10.0 / 2.5)") // 4.0
        
        /*
         溢出操作符号：
         254 : 1111 1110
         100 : 0110 0100
         二进制相加: 0110 0010 (十进制98)
         */
        var a:UInt8 = 254
        print("UInt8：a = ", a)
//        a += 100 // 不使用溢出操作符 编译报错❌
//        print("不使用溢出操作符 a =", a)
        
        a &+= 100
        print("使用溢出操作符(a &+= 100)：a + 100 =", a) // a + 100 = 98
        
        /* 加法运算符支持 String 拼接 */
        let helloworld = "hello, " + "world" // "hello, world"
        print("hello, + world = \(helloworld)")
        
        printEndLine(title)
    }
    
    /// 3.1 余数运算符
    func remainderOperator() {
        
        let title = "3.1 余数运算符";
        printStartLine(title)
        
        print("9 % 4 = \(9 % 4)") // 1
        print("-9 % 4 = \(-9 % 4)") // -1
        
        /* a % b ，b 为 负数时将被忽略：a % b  等价于 a % -b */
        let a = 9
        let b = -4
        let r1 = a % b
        let r2 = a % -b
        print("\(a) % \(b) = \(r1)")
        print("\(a) % \(-b) = \(r2)")
        
        // 🤔 a % b，b 永远被当成了正数 => 余数为正，a为正；余数为负，a为负。
        
        
        printEndLine(title)
    }
    
    /// 3.2 一元减号运算符
    func unaryMinusOperator() {
        
        let title = "3.2 一元减号运算符";
        printStartLine(title)
        
        let three = 3
        let minusThree = -three // -3
        let plusThree = -minusThree // 3
        print("minusThree = \(minusThree)")
        print("plusThree = \(plusThree)")
        
        printEndLine(title)
    }
    
    /// 3.3 一元加号运算符
    func unaryPlusOperator() {
        
        let title = "3.3 一元加号运算符";
        printStartLine(title)
        
        let minusSix = -6
        let alsoMinusSix = +minusSix
        print("minusSix = \(minusSix)")
        print("alsoMinusSix = \(alsoMinusSix)")
        
        printEndLine(title)
        
    }
    
    /// 4.0 组合赋值符号
    func compoundAssignmentOperators() {
        
        let title = "4.0 组合赋值符号";
        printStartLine(title)
        
        var a = 1
        a += 2
        print("a = \(a)") // a = 3
        
        printEndLine(title)
    }
    
    /// 5.0 比较运算符
    func comparisonOperators() {
        
        let title = "5.0 比较运算符";
        printStartLine(title)
        
        /* 每个比较运算符都会返回一个 Bool 值来表示语句是否为真 */
        let r1 = 1 == 1 // true, because 1 is equal to 1
        let r2 = 2 != 1 // true, because 2 is not equal to 1
        let r3 = 2 > 1 // true, because 2 is greater than 1
        let r4 = 1 < 2 // true, because 1 is less than 2
        let r5 = 1 >= 1 // true, because 1 is greater than or equal to 1
        let r6 = 2 <= 1 // false, because 2 is not less than or equal to 1
        print(r1, r2, r3, r4, r5, r6)
        
        /* 比较运算符通常被用在条件语句当中，比如说 if 语句： */
        let name = "world"
        if name == "world" {
            print("hello, world")
        } else {
            print("I'm sorry \(name), but I don't recognize you")
        }
        // "hello, world"
        
        /* 元组仅支持小于 7 个元素比较，以从左到右的顺序比较大小，一次一个值，直到找到两个不相等的值为止 */
        let r7 = (1, "zebra") < (2, "apple")   // true, 1 < 2
        let r8 = (3, "apple") < (3, "bird")    // true, 3 == 3, "apple" < "bird"
        let r9 = (4, "dog") == (4, "dog")      // true, 4 == 4, "dog" == "dog"
        
        print(r7, r8, r9)
        
        /* Bool 不能比较，包含布尔值的元组不能用来比较大小 */
//        let r10 = ("blue", false) < ("purple", true)  // Error
        
        printEndLine(title)
    }
    
    /// 6.0 三元条件运算符
    func ternaryConditionalOperator() {
        
        let title = "6.0 三元条件运算符";
        printStartLine(title)
        
        /* 每个比较运算符都会返回一个 Bool 值来表示语句是否为真 */
        let contentHeight = 40
        let hasHeader = true
        let rowHeight = contentHeight + (hasHeader ? 50 : 20)
        
        print(rowHeight) // 90
        
        printEndLine(title)
    }
    
    /// 7.0 合并空值运算符
    func nilCoalescingOperator() {
        
        let title = "7.0 合并空值运算符";
        printStartLine(title)
        
        /* 使用了合并空值运算符来在默认颜色名和可选的用户定义颜色名之间做选择：*/
        let defaultColorName = "red"
        var userDefinedColorName: String? // defaults to nil
        var colorNameToUse = userDefinedColorName ?? defaultColorName
        
        print(colorNameToUse)
        
        userDefinedColorName = "green"
        colorNameToUse = userDefinedColorName ?? defaultColorName
        
        print(colorNameToUse)

        printEndLine(title)
    }
    
    /// 8.1 闭区间运算符
    func closedRangeOperator() {
        
        let title = "8.1 闭区间运算符";
        printStartLine(title)
        
        // ... 在 for-in
        for index in 1...5 {
            print("\(index) times 5 is \(index * 5)")
        }
        // 1 times 5 is 5
        // 2 times 5 is 10
        // 3 times 5 is 15
        // 4 times 5 is 20
        // 5 times 5 is 25
        
        printEndLine(title)
    }
    
    /// 8.2 半开区间运算符
    func halfOpenRangeOperator() {
        
        let title = "8.2 半开区间运算符";
        printStartLine(title)
        
        // ..< 在遍历基于零开始序列比如说数组的时候非常有用
        let names = ["Anna", "Alex", "Brian", "Jack"]
        let count = names.count
        for i in 0..<count {
            print("Person \(i + 1) is called \(names[i])")
        }
        // Person 1 is called Anna
        // Person 2 is called Alex
        // Person 3 is called Brian
        // Person 4 is called Jack
        
        printEndLine(title)
    }
    
    /// 8.3 单侧区间
    func oneSidedRanges() {
        
        let title = "8.3 单侧区间";
        printStartLine(title)
        
        let names = ["Anna", "Alex", "Brian", "Jack"]
        print(names)
        
        /* 从索引 2 到数组的结束 */
        print("从索引 2 到数组的结束")
        for name in names[2...] {
            print(name)
        }
        // Brian
        // Jack
        
        /* 从数组的开始到索引 2 */
        print("从数组的开始到索引 2")
        for name in names[...2] {
            print(name)
        }
        // Anna
        // Alex
        // Brian
        
        /* 从数组的开始到索引 2(不包括索引2) */
        print("从数组的开始到索引 2(不包括索引2)")
        for name in names[..<2] {
            print(name)
        }
        // Anna
        // Alex
        
        /* 检测单侧区间是否包含特定的值，如：*/
        let range = ...5
        print("range = ", range)
        
        let r1 = range.contains(7)   // false
        let r2 = range.contains(4)   // true
        let r3 = range.contains(-1)  // true
        
        print("range.contains(7): ", r1)
        print("range.contains(4): ", r2)
        print("range.contains(-1): ", r3)
        
        printEndLine(title)
    }
    
    /// 9.1 逻辑非运算符
    func logicalNOTOperator() {
        
        let title = "9.1 逻辑非运算符";
        printStartLine(title)
        
        let allowedEntry = false
        if !allowedEntry {
            print("ACCESS DENIED")
        }
        // prints "ACCESS DENIED"
        
        printEndLine(title)
    }
    
    /// 9.2 逻辑与运算符
    func logicalANDOperator() {
        
        let title = "9.2 逻辑与运算符";
        printStartLine(title)
        
        let enteredDoorCode = true
        let passedRetinaScan = false
        if enteredDoorCode && passedRetinaScan {
            print("Welcome!")
        } else {
            print("ACCESS DENIED")
        }
        // Prints "ACCESS DENIED"
        
        printEndLine(title)
    }
    
    /// 9.3 逻辑或运算符
    func logicalOROperator() {
        
        let title = "9.3 逻辑或运算符";
        printStartLine(title)
        
        let hasDoorKey = false
        let knowsOverridePassword = true
        if hasDoorKey || knowsOverridePassword {
            print("Welcome!")
        } else {
            print("ACCESS DENIED")
        }
        // Prints "Welcome!"
        
        printEndLine(title)
    }
    
    /// 9.4 混合逻辑运算
    func combiningLogicalOperators() {
        
        let title = "9.4 混合逻辑运算";
        printStartLine(title)
        
        let enteredDoorCode = true
        let passedRetinaScan = false
        let hasDoorKey = false
        let knowsOverridePassword = true
        
        // 多个逻辑运算符组合表达式会首先计算最左边的子表达式
        if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
            print("Welcome!")
        } else {
            print("ACCESS DENIED")
        }
        // Prints "Welcome!"
        
        printEndLine(title)
    }
    
    /// 9.5 显式括号
    func explicitParentheses() {
        
        let title = "9.5 显式括号";
        printStartLine(title)
        
        let enteredDoorCode = true
        let passedRetinaScan = false
        let hasDoorKey = false
        let knowsOverridePassword = true
        
        if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
            print("Welcome!")
        } else {
            print("ACCESS DENIED")
        }
        // Prints "Welcome!"
        
        printEndLine(title)
    }
}

